﻿using System.Globalization;
using System.Text;
using System.Text.Json;

namespace SwaggerDoc.Api
{
    /// <summary>
    /// NameString
    /// </summary>
    public static class NameString
    {
        /// <summary>
        /// SeparatedCaseState
        /// </summary>
        private enum SeparatedCaseState
        {
            Start,
            Lower,
            Upper,
            NewWord
        }

        /// <summary>
        /// ToSeparatedCase
        /// </summary>
        /// <param name="s"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        private static string ToSeparatedCase(this string s, char separator)
        {
            if (string.IsNullOrEmpty(s))
            {
                return s;
            }

            StringBuilder stringBuilder = new StringBuilder();
            SeparatedCaseState separatedCaseState = SeparatedCaseState.Start;
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] == ' ')
                {
                    if (separatedCaseState != 0)
                    {
                        separatedCaseState = SeparatedCaseState.NewWord;
                    }
                }
                else if (char.IsUpper(s[i]))
                {
                    switch (separatedCaseState)
                    {
                        case SeparatedCaseState.Upper:
                            {
                                bool flag = i + 1 < s.Length;
                                if (i > 0 && flag)
                                {
                                    char c = s[i + 1];
                                    if (!char.IsUpper(c) && c != separator)
                                    {
                                        stringBuilder.Append(separator);
                                    }
                                }

                                break;
                            }
                        case SeparatedCaseState.Lower:
                        case SeparatedCaseState.NewWord:
                            stringBuilder.Append(separator);
                            break;
                    }

                    char value = char.ToLower(s[i], CultureInfo.InvariantCulture);
                    stringBuilder.Append(value);
                    separatedCaseState = SeparatedCaseState.Upper;
                }
                else if (s[i] == separator)
                {
                    stringBuilder.Append(separator);
                    separatedCaseState = SeparatedCaseState.Start;
                }
                else
                {
                    if (separatedCaseState == SeparatedCaseState.NewWord)
                    {
                        stringBuilder.Append(separator);
                    }

                    stringBuilder.Append(s[i]);
                    separatedCaseState = SeparatedCaseState.Lower;
                }
            }

            return stringBuilder.ToString();
        }

        /// <summary>
        /// ToLower
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private static char ToLower(this char c)
        {
            c = char.ToLower(c, CultureInfo.InvariantCulture);
            return c;
        }

        /// <summary>
        /// 驼峰
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToCamelCase(this string s)
        {
            if (string.IsNullOrEmpty(s) || !char.IsUpper(s[0]))
            {
                return s;
            }

            char[] array = s.ToCharArray();
            for (int i = 0; i < array.Length && (i != 1 || char.IsUpper(array[i])); i++)
            {
                bool flag = i + 1 < array.Length;
                if (i > 0 && flag && !char.IsUpper(array[i + 1]))
                {
                    if (char.IsSeparator(array[i + 1]))
                    {
                        array[i] = ToLower(array[i]);
                    }

                    break;
                }

                array[i] = ToLower(array[i]);
            }

            return new string(array);
        }

        /// <summary>
        /// 蛇形
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToSnakeCase(this string s)
        {
            return ToSeparatedCase(s, '_');
        }

        /// <summary>
        /// 中横线
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToKebabCase(this string s)
        {
            return ToSeparatedCase(s, '-');
        }
    }

    /// <summary>
    /// 返回驼峰
    /// </summary>
    public class CamelCasePolicy : JsonNamingPolicy
    {
        /// <summary>
        /// 返回驼峰
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public override string ConvertName(string name) =>
            name.ToCamelCase();
    }

    /// <summary>
    /// 返回对象全小写
    /// </summary>
    public class LowerCasePolicy : JsonNamingPolicy
    {
        /// <summary>
        /// 返回对象全小写
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public override string ConvertName(string name) =>
            name.ToLower();
    }

    /// <summary>
    /// 返回对象蛇形
    /// </summary>
    public class SnakeCasePolicy : JsonNamingPolicy
    {
        /// <summary>
        /// 返回对象蛇形
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public override string ConvertName(string name) => name.ToSnakeCase();
    }

    /// <summary>
    /// 返回对象中横线
    /// </summary>
    public class KebabCasePolicy : JsonNamingPolicy
    {
        /// <summary>
        /// 返回对象中横线
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public override string ConvertName(string name) => name.ToKebabCase();
    }
}
